
package com.icehand.utils.encryption;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;

/**
 * AES
 */
public class AES {
	/**
	 * AES 加密
	 * @param key
	 *            开发者自己的AES秘钥
	 * @param content
	 *            需要加密的参数
	 * @param charset
	 *            项目使用的字符编码集
	 * @return string
	 * @throws Exception ex
	 */
	public static String encrypt(String key, String content, String charset) throws Exception {
		String fullAlg = "AES/CBC/PKCS5Padding";

		Cipher cipher = Cipher.getInstance(fullAlg);
		IvParameterSpec iv = new IvParameterSpec(initIv(fullAlg));
		cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Base64.decode(key), "AES"), iv);

		byte[] encryptBytes = cipher.doFinal(content.getBytes(charset));
		return Base64.encode(encryptBytes);
	}

	/**
	 * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节).
	 *
	 * @param fullAlg str
	 * @return bytes
	 * @throws GeneralSecurityException ex
	 */
	private static byte[] initIv(String fullAlg) throws GeneralSecurityException {
		Cipher cipher = Cipher.getInstance(fullAlg);
		int blockSize = cipher.getBlockSize();
		byte[] iv = new byte[blockSize];
		for (int i = 0; i < blockSize; ++i) {
			iv[i] = 0;
		}
		return iv;
	}

	/**
	 * AES解密
	 * @param content
	 *            密文
	 * @param key
	 *            aes密钥
	 * @param charset
	 *            字符集
	 * @return 原文
	 * @throws Exception ex
	 */
	public static String decrypt(String content, String key, String charset) throws Exception {

		// 反序列化AES密钥
		SecretKeySpec keySpec = new SecretKeySpec(Base64.decode(key), "AES");

		// 128bit全零的IV向量
		byte[] iv = new byte[16];
		for (int i = 0; i < iv.length; i++) {
			iv[i] = 0;
		}
		IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

		// 初始化加密器并加密
		Cipher deCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		deCipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
		byte[] encryptedBytes = Base64.decode(content);
		byte[] bytes = deCipher.doFinal(encryptedBytes);
		return new String(bytes);

	}
}
